#include <cmath>
#include <QDebug>
#include <QFontMetrics>
#include "element.h"

DrawDots2Line::DrawDots2Line(void)
{
    m_line_start = QPoint(0, 0);
    m_line_end = QPoint(0, 0);
    m_distance = 0.0;
    m_drawType = DOTSTOLINE;
    m_state = DS_IDLE;
    m_dots_start.clear();
    m_dots_end.clear();
    m_tempEnd = QPoint(0, 0);
}

inline void DrawDots2Line::setStartPoint(QPoint point)
{
    m_line_start = point;
    m_line_end = point;
    m_state = Element::DS_STATE1; // 表明线的起点已经确定，终点还没确定
}
inline void DrawDots2Line::setTempEndPoint(QPoint point)
{
    m_line_end = point;
}
inline void DrawDots2Line::setEndPoint(QPoint point)
{
    m_line_end = point;
    if (m_line_end == m_line_start)
    {
             m_state = DS_ERROR;
    }
            else
    {
            m_state = Element::DS_STATE2; // 表示线已经完全确定了
    }
}
void DrawDots2Line::computeBox(void)
{
    int min_x, max_x, min_y, max_y;
    min_x = qMin(m_dots_start.last().x(), m_dots_end.last().x());
    max_x = qMax(m_dots_start.last().x(), m_dots_end.last().x());
    min_y = qMin(m_dots_start.last().y(), m_dots_end.last().y());
    max_y = qMax(m_dots_start.last().y(), m_dots_end.last().y());
    m_box.setCoords ( min_x, min_y, max_x, max_y );
}
inline void DrawDots2Line::setStartDot(QPoint point)
{
    m_dots_start.clear();
    m_dots_end.clear();
    m_dots_start.push_back(point);
    computeEndDot();
    computeDist(); // 得到点与线间的距离
    m_tempEnd = point;
    m_state = Element::DS_STATE3; //  确定了线和至少一个点


    int X = ( m_dots_start.last().x() + m_dots_end.last().x() ) / 2;
    int Y = ( m_dots_start.last().y() + m_dots_end.last().y() ) / 2;
    m_textBoxs.push_back(QRect(X,Y,1,1));
    updateText();
}
inline void DrawDots2Line::setMidDot(QPoint point)
{
    if(m_dots_start.last() != point)
    {
        m_dots_start.push_back(point);
        computeEndDot();
        computeDist();

        m_tempEnd = point;
        int X = ( m_dots_start.last().x() + m_dots_end.last().x() ) / 2;
        int Y = ( m_dots_start.last().y() + m_dots_end.last().y() ) / 2;
        m_textBoxs.push_back(QRect(X,Y,1,1));
        //m_textBox.moveTo(X, Y);
        updateText();
    }
}
void DrawDots2Line::setTempEndDot(QPoint point)
{
    m_tempEnd = point;
}
void DrawDots2Line::setEndDot(QPoint point)
{
    m_dots_start.push_back(point);
    computeEndDot();
    computeDist();
    int X = ( m_dots_start.last().x() + m_dots_end.last().x() ) / 2;
    int Y = ( m_dots_start.last().y() + m_dots_end.last().y() ) / 2;
    m_textBoxs.push_back(QRect(X,Y,1,1));
    //m_textBox.moveTo(X, Y);
    updateText();
    m_state = Element::DS_FINISH;
}

void DrawDots2Line::build(QPoint p1, QPoint p2, QVector<QPoint> points)
{
    setStartPoint(p1);
    setEndPoint(p2);
    m_dots_start = points;
    computeDist();
    computeEndDot();
    updateText();
    m_state = Element::DS_FINISH;
}

int DrawDots2Line::mouseRButtonPress(QPoint point)
{
    if(m_state == DS_STATE3)
    {
        setEndDot(point);
        return 1;
    }
    return 0;
}
int DrawDots2Line::mouseLButtonPress(QPoint point)
{
    if( m_state == DS_IDLE )
    {
        setStartPoint(point);
        return 1;
    }
    if(m_state == DS_STATE2)
    {
        setStartDot(point);
        return 2;
    }
    if(m_state == DS_STATE3)
    {
        setMidDot(point);
        return 3;
    }
    return 0;
}
int DrawDots2Line::mouseLButtonRelease(QPoint point)
{
    if( m_state == DS_STATE1 )
    {
        setEndPoint(point);
        return 1;
    }
    return 0;
}
int	DrawDots2Line::mouseMove(QPoint point)
{
    if( m_state == DS_STATE1 ) // 线的终点还没确定, 这时鼠标左键肯定是按下的
    {
        setTempEndPoint(point);
        return 1;
    }
    else if( m_state == DS_STATE2 && m_state == DS_STATE3) // 线已经确定了，这里要确定线外的点。
    {
        setTempEndDot(point);
        return 1;
    }
    return 0;
}

void DrawDots2Line::computeDist(void)
{
    //计算点到直线的距离
    //点P(X,Y)到直线Ax+By+C=0的距离为 |AX+BY+C| 除以 根号下(A^2+B^2)
    //直线公式(x-x1)/(x2-x1)=(y-y1)/(y2-y1)--》(y2-y1)x+(x1-x2)y-x1(y2-y1)+y1(x2-x1)=0
    //////////////////////////////////////////////////////////////////////////
    double A = m_line_end.y() - m_line_start.y();
    double B = m_line_start.x() - m_line_end.x();
    double C = - m_line_start.x() * A - m_line_start.y() * B;
    m_distance = abs(A * m_dots_start.last().x() + B * m_dots_start.last().y() + C ) / hypot(A, B);
}
void DrawDots2Line::computeEndDot(void)
{
    //计算直线外一点在直线上的垂足
    //点P(X,Y)在直线Ax+By+C=0上的垂足为
    //x=(B*B*X-A*B*Y-A*C)/(A*A+B*B)
    //y=(-A*B*X+A*A*Y-B*C)/(A*A+B*B)
    //直线公式(x-x1)/(x2-x1)=(y-y1)/(y2-y1)--》(y2-y1)x+(x1-x2)y-x1(y2-y1)+y1(x2-x1)=0
    double A = m_line_end.y() - m_line_start.y();
    double B = m_line_start.x() - m_line_end.x();
    double C = - m_line_start.x() * A - m_line_start.y() * B;
    double x = (B * B * m_dots_start.last().x()- A * B * m_dots_start.last().y() - A * C)/(A * A + B * B);
    double y = (-A * B * m_dots_start.last().x() + A * A  * m_dots_start.last().y() - B * C) / (A * A + B * B);
    m_dots_end.push_back(QPoint(x,y));
}

void DrawDots2Line::updateText(void)
{
    //m_text = QString(tr("D = %1 um")).arg(m_distance * m_scale, 2, 'f', 2);
    m_texts.push_back(QString("non"));

    if(m_distance * m_scale >= 1000.0)
    {
        m_texts.last() = QString::fromUtf8(u8"%1 mm").arg(m_distance * m_scale / 1000.0, 2, 'f', 2);
    }
    else
    {
        m_texts.last() = QString::fromUtf8(u8"%1 μm").arg(m_distance * m_scale, 2, 'f', 2);
    }
    QFontMetrics fm(m_textFont);
    int textWidth = fm.width(m_texts.last());
    int textHeight = fm.height();
    m_textBoxs.last().setWidth(textWidth);
    m_textBoxs.last().setHeight(textHeight);
}
void DrawDots2Line::draw( QPainter &painter )
{
    if( m_state != DS_IDLE )
    {
        painter.save();
        painter.setPen(m_linePen);
        painter.drawLine (m_line_start, m_line_end - QPoint(1, 1) );
        painter.drawLine(m_line_start, m_line_end);

        if( m_state == DS_STATE3 )
        {

            painter.drawLine(m_line_start, m_line_end);
            int N = m_dots_start.size();
            for(int i = 0; i < N; i ++)
            {

                painter.drawLine(m_dots_start[i], m_dots_end[i]);
                painter.setFont(m_textFont);
                painter.drawText(m_textBoxs[i], m_texts[i]);

            }
        }
            //painter.drawLines(m_dots);

        if(m_state == DS_FINISH)
        {

            int N = m_dots_start.size();
            for(int i = 0; i < N; i ++)
            {

                painter.drawLine(m_dots_start[i], m_dots_end[i]);
                painter.setFont(m_textFont);
                painter.drawText(m_textBoxs[i], m_texts[i]);

            }
        }
    }
    painter.restore();
}

